import urllib2
import re

# CAMERA CONTROL CODE -----------------------------------------------------------------------------
# -------------------------------------------------------------------------------------------------
# given a codebase URL, connect to the camera, and return the connection ID.  If failure, return -1.
def connectToCamera(baseURL):
	assert baseURL[-1] == '/', 'Base URL has to end in /'
	assert baseURL[0:7] == 'http://', 'Base URL must begin with http://'
	response = urllib2.urlopen(baseURL + '-wvhttp-01-/OpenCameraServer')#'?client_version=LiveApplet')
	message = response.read()
	if len(message) < 14 or message[0:13] != 'connection_id':
		return -1;
	else:
		return message[14:23]
	
# place yourself in the queue.  Returns true if successful, false otherwise.
def getCameraControl(baseURL, connectionID):
	#  http://grizcam.ito.umt.edu/-wvhttp-01-/GetCameraControl?connection_id=4009-1234
	assert baseURL[-1] == '/', 'Base URL has to end in /'
	assert baseURL[0:7] == 'http://', 'Base URL must begin with http://'
	response = urllib2.urlopen(baseURL + '-wvhttp-01/GetCameraControl?connection_id=' + connectionID)
	message = response.read()
	return message == 'OK.\n'
	
# operate the camera.
# returns 'success' if the camera moved,
#         'unknown connection' if the connection is out-of-date or has not been made.
#         'not your turn' if it is not your turn.
#         'failure' if there is some other failure.
def operateCamera(baseURL, connectionID, pan, tilt, zoom):
	# http://grizcam.ito.umt.edu/-wvhttp-01-/OperateCamera?zoom=-179&connection_id=4009-1234
	assert baseURL[-1] == '/', 'Base URL has to end in /'
	assert baseURL[0:7] == 'http://', 'Base URL must begin with http://'
	params = ''
	if pan:
		params = params + 'pan=' + str(pan) + '&';
	if tilt:
		params = params + 'tilt=' + str(tilt) + '&';
	if zoom:
		params = params + 'zoom=' + str(zoom) + '&';
	assert params != '', 'Pan, tilt, and zoom cannot all be empty.'
	response = urllib2.urlopen(baseURL + '-wvhttp-01/OperateCamera?' + params + 'connection_id=' + connectionID)
	message = response.read()
	if message == 'OK.\n':
		return 'success'
	elif message[0:65] == '--- WebView Livescope Http Server Error ---\nUnknown Connection ID':
		return 'unknown connection'
	elif message == '--- WebView Livescope Http Server Error ---\nNo Camera Control Right\n':
		return 'not your turn'
	else:
		return 'failure'
	return message
	
	
	
# HTML PARSER CODE --------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------------------
class CodeBaseNotFoundError(Exception):
	def __init__(self, msg):
		self.msg = msg

def findCodeBaseURL(sourceURL):
	# from a source URL, try to find the code base URL.
	#  examples:
	# <applet archive="LiveApplet.zip" codebase="http://128.151.54.230/-wvdoc-01-/LiveApplet/"
	# <applet archive="LiveApplet.zip" codebase="http://grizcam.ito.umt.edu/-wvdoc-01-/LiveApplet/"
	# <param name="url"		value="http://grizcam.ito.umt.edu/"/>

	
	# Raises an IOError if we can't read sourceURL.
	# Raises a CodeBaseNotFoundError if we can't find the code base.

	response = urllib2.urlopen(sourceURL)
	lines = response.readlines()
	response.close()
	return searchForCodeBase(lines)

# parse through an HTML document to find the codebase for a java applet, given
# a list of lines in the document.
def searchForCodeBase(lines):
	regStart = '.*<applet.*archive *= *"LiveApplet.zip"'
	regCodeBase = '.*codebase *= *"(.*LiveApplet/)".*'
	regBaseURL  = '(http://[^/]*).*'
	regEnd = '.*</applet>'
	regexStart    = re.compile(regStart, re.IGNORECASE)
	regexCodeBase = re.compile(regCodeBase, re.IGNORECASE)
	regexBaseURL  = re.compile(regBaseURL, re.IGNORECASE)
	regexEnd      = re.compile(regEnd, re.IGNORECASE)
	
	listeningForCodeBase = False
	codeBase = None
	baseURL  = None
	for line in lines:
		
		match = regexStart.match(line)
		if (match):
			listeningForCodeBase = True
		
		if (listeningForCodeBase):
			match = regexCodeBase.match(line)
			if (match):
				codeBase = match.group(1)
				
				match = regexBaseURL.match(codeBase)
				if (match):
					baseURL = match.group(1)
					return baseURL, codeBase
				else:
					raise CodeBaseNotFoundError('Could not find code base.')
		
		match = regexEnd.match(line)
		if (match):
			codeBase = None
			baseURL = None
			listeningForCodeBase = False
			
	raise CodeBaseNotFoundError('Could not find code base.')

# given a codebase URL, parse through and find the current pan, tilt, and zoom values.
def getCurrentPanTiltZoom(baseURL):
	pan = None
	tilt = None
	zoom = None
	
	if baseURL[-1] != '/':
		baseURL = baseURL + '/'
		
	response = urllib2.urlopen(baseURL + '-wvhttp-01-/GetCameraInfo')
	lines = response.readlines()
	response.close()
	
	regexPan    = re.compile('pan_current_value=(.*)')
	regexTilt   = re.compile('tilt_current_value=(.*)')
	regexZoom   = re.compile('zoom_current_value=(.*)')
	for line in lines:
		if pan and tilt and zoom:
			break
			
		match = regexPan.match(line)
		if (match):
			pan = match.group(1)
			continue
			
		match = regexTilt.match(line)
		if (match):
			tilt = match.group(1)
			continue
			
		match = regexZoom.match(line)
		if (match):
			zoom = match.group(1)
			continue
	return pan, tilt, zoom
			
			
# given a codebase URL, find the pan, tilt, and zoom ranges.
def getPanTiltZoomRanges(baseURL):
	panLeft = None
	panRight = None
	tiltUp = None
	tiltDown = None
	zoomIn = None
	zoomOut = None
	cameraType = None
	
	if baseURL[-1] != '/':
		baseURL = baseURL + '/'
		
	response = urllib2.urlopen(baseURL + '-wvhttp-01-/GetCameraInfo')
	lines = response.readlines()
	response.close()
	
	regexPanLeft     = re.compile('pan_left_end=(.*)')
	regexPanRight    = re.compile('pan_right_end=(.*)')
	regexTiltUp      = re.compile('tilt_up_end=(.*)')
	regexTiltDown    = re.compile('tilt_down_end=(.*)')
	regexZoomIn      = re.compile('zoom_tele_end=(.*)')
	regexZoomOut     = re.compile('zoom_wide_end=(.*)')
	regexCameraType  = re.compile('camera_type=(.*)')
	for line in lines:
		if zoomIn and zoomOut and tiltUp and tiltDown and panLeft and panRight and cameraType :
			break
			
		match = regexCameraType.match(line)
		if (match):
			cameraType = match.group(1)
			continue
			
		match = regexPanLeft.match(line)
		if (match):
			panLeft = float(match.group(1))
			continue
			
		match = regexPanRight.match(line)
		if (match):
			panRight = float(match.group(1))
			continue
			
		match = regexTiltUp.match(line)
		if (match):
			tiltUp = float(match.group(1))
			continue
		
		match = regexTiltDown.match(line)
		if (match):
			tiltDown = float(match.group(1))
			continue
			
		match = regexZoomIn.match(line)
		if (match):
			zoomIn = float(match.group(1))
			continue
		
		match = regexZoomOut.match(line)
		if (match):
			zoomOut = float(match.group(1))
			continue
			
	return panLeft, panRight, tiltUp, tiltDown, zoomIn, zoomOut, cameraType